﻿using AutoRevit.Extensions;
using AutoRevit.ThreadTask;
using System.Runtime.CompilerServices;

namespace AutoRevit.Event;

/// <summary>
/// 外部事件精简使用
/// </summary>
public class ExternalEventHandlerLite : IExtensionsExternalEventHandler, IExternalEventHandler, IDisposable
{
    private readonly object _lock;

    private readonly ExternalEvent _revitEvent;

    private readonly TaskFactory actionToRevitTaskFactory = new TaskFactory(new LimitedConcurrencyLevelTaskScheduler());

    private readonly string _eventName;

    private ExternalEventHandlerInfo? handlerInfo;

    /// <summary>
    /// 外部事件执行时事件
    /// </summary>
    public event ExecuteHandler? OnExecutein;

    /// <summary>
    /// 外部事件执行完成后事件
    /// </summary>
    public event ExecuteHandler? OnExecuteed;

    /// <summary>
    /// 外部事件执行错误事件
    /// </summary>
    public event ExecuteExceptionHandler? OnException;

    /// <summary>
    /// 创建一个新外部事件实例
    /// </summary>
    /// <param name="name"></param>
    /// <returns></returns>
    public static ExternalEventHandlerLite Create(string name = "") => new ExternalEventHandlerLite(name);

    /// <summary>
    /// 实例化
    /// </summary>
    /// <param name="name"></param>
    public ExternalEventHandlerLite([CallerMemberName] string name = "")
    {
        _revitEvent = ExternalEvent.CreateJournalable(this);
        _eventName = name;
        _lock = new object();
    }

    /// <summary>
    ///
    /// </summary>
    /// <param name="app"></param>
    void IExternalEventHandler.Execute(UIApplication app)
    {
        lock (_lock)
        {
            try
            {
                OnExecutein?.Invoke(app);
                handlerInfo?.Execute(app);
                OnExecuteed?.Invoke(app);
            }
            catch (Exception ex)
            {
                OnException?.Invoke(app, ex);
                throw;
            }
            finally
            {
                handlerInfo = null;
            }
        }
    }

    /// <summary>
    /// 获取当前名称
    /// </summary>
    /// <returns></returns>
    public string GetName() => string.IsNullOrWhiteSpace(_eventName) ? GetType().Name : _eventName;

    #region 执行外部事件函数

    /// <summary>
    /// 
    /// </summary>
    /// <param name="handlerInfo"></param>
    public void Execute(ExternalEventHandlerInfo handlerInfo)
    {
        void taskRun(ExternalEventHandlerInfo info)
        {
            while (this.handlerInfo != null) ;

            this.handlerInfo = info;

            _revitEvent.Raise();
        }

        actionToRevitTaskFactory.StartNew(taskRun, handlerInfo);
    }

    /// <summary>
    /// 执行外部事件
    /// </summary>
    /// <param name="raiseCommandEvent"></param>
    public void Execute(Action<UIApplication> raiseCommandEvent)
    {
        var actionHandler = new ExternalEventHandlerInfo(raiseCommandEvent);

        Execute(actionHandler);
    }

    /// <summary>
    /// 释放外部事件
    /// </summary>
    public void Dispose()
    {
        _revitEvent.Dispose();
    }

    #endregion 执行外部事件函数
}
